/// Text utility for string manipulation and formatting.
/// 文本字符串操作和格式化工具
///
/// Original author: Sky24n (https://github.com/Sky24n)
/// Updated by: sunlunchang
library;

/// Text utility class providing string manipulation methods.
/// 文本工具类，提供字符串操作方法
class TextUtil {
  /// Double quotes character / 双引号字符
  static const String doubleQuotes = '"';

  /// Single quote character / 单引号字符
  static const String singleQuote = '\'';

  /// Ampersand character / 和号字符
  static const String amp = '&';

  /// Less than character / 小于号字符
  static const String lt = '<';

  /// Greater than character / 大于号字符
  static const String gt = '>';

  /// Space character / 空格字符
  static const String space = ' ';

  /// Tab character / 制表符
  static const String tab = '\t';

  /// Dot character / 点号字符
  static const String dot = '.';

  /// Double dot (parent directory) / 双点号（父目录）
  static const String doubleDot = '..';

  /// Forward slash / 正斜杠
  static const String slash = '/';

  /// Backslash / 反斜杠
  static const String backslash = '\\';

  /// Empty string / 空字符串
  static const String empty = '';

  /// Null string representation / null 字符串表示
  static const String nullString = 'null';

  /// Carriage return / 回车符
  static const String cr = '\r';

  /// Line feed / 换行符
  static const String lf = '\n';

  /// Carriage return + line feed / 回车换行符
  static const String crlf = '\r\n';

  /// Underscore character / 下划线字符
  static const String underline = '_';

  /// Dash character / 短横线字符
  static const String dashed = '-';

  /// Comma character / 逗号字符
  static const String comma = ',';

  /// Opening curly brace / 左花括号
  static const String delimStart = '{';

  /// Closing curly brace / 右花括号
  static const String delimEnd = '}';

  /// Opening square bracket / 左方括号
  static const String bracketStart = '[';

  /// Closing square bracket / 右方括号
  static const String bracketEnd = ']';

  /// Colon character / 冒号字符
  static const String colon = ':';

  /// HTML non-breaking space / HTML 不间断空格
  static const String htmlNbsp = '&nbsp;';

  /// HTML ampersand / HTML 和号
  static const String htmlAmp = '&amp;';

  /// HTML double quote / HTML 双引号
  static const String htmlQuote = '&quot;';

  /// HTML apostrophe / HTML 撇号
  static const String htmlApos = '&apos;';

  /// HTML less than / HTML 小于号
  static const String htmlLt = '&lt;';

  /// HTML greater than / HTML 大于号
  static const String htmlGt = '&gt;';

  /// Empty JSON object / 空 JSON 对象
  static const String emptyJson = '{}';

  /// Checks if text is null or empty.
  /// 检查文本是否为 null 或空
  ///
  /// [text] The text to check / 要检查的文本
  /// Returns true if text is null or empty / 如果文本为 null 或空则返回 true
  static bool isEmpty(String? text) {
    return text == null || text.isEmpty;
  }

  /// Checks if text is not null and not empty.
  /// 检查文本是否不为 null 且不为空
  ///
  /// [text] The text to check / 要检查的文本
  /// Returns true if text is not null and not empty / 如果文本不为 null 且不为空则返回 true
  static bool isNotEmpty(String? text) {
    return !isEmpty(text);
  }

  /// Formats text by inserting a pattern every N digits.
  /// 通过每 N 位插入一个模式来格式化文本
  ///
  /// [text] The text to format / 要格式化的文本
  /// [digit] Number of digits between patterns (default: 4) / 模式之间的位数（默认：4）
  /// [pattern] Pattern to insert (default: space) / 要插入的模式（默认：空格）
  ///
  /// Example / 示例: formatDigitPattern('12345678', digit: 4) => '1234 5678'
  static String formatDigitPattern(String text,
      {int digit = 4, String pattern = ' '}) {
    text = text.replaceAllMapped(RegExp('(.{$digit})'), (Match match) {
      return '${match.group(0)}$pattern';
    });
    if (text.endsWith(pattern)) {
      text = text.substring(0, text.length - 1);
    }
    return text;
  }

  /// Formats text by inserting a pattern every N digits from the end.
  /// 从末尾开始每 N 位插入一个模式来格式化文本
  ///
  /// [text] The text to format / 要格式化的文本
  /// [digit] Number of digits between patterns (default: 4) / 模式之间的位数（默认：4）
  /// [pattern] Pattern to insert (default: space) / 要插入的模式（默认：空格）
  ///
  /// Example / 示例: formatDigitPatternEnd('12345678', digit: 3) => '12 345 678'
  static String formatDigitPatternEnd(String text,
      {int digit = 4, String pattern = ' '}) {
    String temp = reverse(text);
    temp = formatDigitPattern(temp, digit: digit, pattern: pattern);
    temp = reverse(temp);
    return temp;
  }

  /// Formats text by adding space every 4 digits.
  /// 每 4 位添加空格来格式化文本
  ///
  /// [text] The text to format / 要格式化的文本
  ///
  /// Example / 示例: formatSpace4('1234567890') => '1234 5678 90'
  static String formatSpace4(String text) {
    return formatDigitPattern(text);
  }

  /// Formats number with comma separators (thousands separator).
  /// 使用逗号分隔符格式化数字（千位分隔符）
  ///
  /// [num] Number or number string (integer type) / 数字或数字字符串（整数类型）
  ///
  /// Example / 示例: formatComma3(1234567) => '1,234,567'
  static String formatComma3(Object num) {
    return formatDigitPatternEnd(num.toString(), digit: 3, pattern: ',');
  }

  /// Formats double number with comma separators.
  /// 使用逗号分隔符格式化浮点数
  ///
  /// [num] Number or number string (double type) / 数字或数字字符串（浮点类型）
  /// [digit] Number of digits between separators (default: 3) / 分隔符之间的位数（默认：3）
  /// [pattern] Separator pattern (default: comma) / 分隔符模式（默认：逗号）
  ///
  /// Example / 示例: formatDoubleComma3(1234567.89) => '1,234,567.89'
  static String formatDoubleComma3(Object num,
      {int digit = 3, String pattern = ','}) {
    final list = num.toString().split('.');
    final left = formatDigitPatternEnd(list[0], digit: digit, pattern: pattern);
    final right = list[1];
    return '$left.$right';
  }

  /// Hides part of a phone number or string.
  /// 隐藏电话号码或字符串的一部分
  ///
  /// [phoneNo] The phone number to hide / 要隐藏的电话号码
  /// [start] Start index of hidden part (default: 3) / 隐藏部分的起始索引（默认：3）
  /// [end] End index of hidden part (default: 7) / 隐藏部分的结束索引（默认：7）
  /// [replacement] Replacement string (default: '****') / 替换字符串（默认：'****'）
  ///
  /// Example / 示例: hideNumber('13812345678') => '138****5678'
  static String hideNumber(String phoneNo,
      {int start = 3, int end = 7, String replacement = '****'}) {
    return phoneNo.replaceRange(start, end, replacement);
  }

  /// Replaces all occurrences of a pattern in text.
  /// 替换文本中所有出现的模式
  ///
  /// [text] The text to process / 要处理的文本
  /// [from] Pattern to find / 要查找的模式
  /// [replace] Replacement string / 替换字符串
  /// Returns null if text is null or empty / 如果文本为 null 或空则返回 null
  static String? replace(String? text, Pattern from, String replace) {
    if (isEmpty(text)) {
      return null;
    }
    return text!.replaceAll(from, replace);
  }

  /// Splits text by pattern.
  /// 按模式分割文本
  ///
  /// [text] The text to split / 要分割的文本
  /// [pattern] Split pattern / 分割模式
  /// Returns empty list if text is null or empty / 如果文本为 null 或空则返回空列表
  static List<String> split(String? text, Pattern pattern) {
    if (isEmpty(text)) {
      return List.empty(growable: true);
    }
    return text!.split(pattern);
  }

  /// Reverses the text.
  /// 反转文本
  ///
  /// [text] The text to reverse / 要反转的文本
  ///
  /// Example / 示例: reverse('hello') => 'olleh'
  static String reverse(String? text) {
    if (isEmpty(text)) return '';
    return text!.split('').reversed.join();
  }

  /// Adds prefix to string if it doesn't already start with it.
  /// 如果字符串不以前缀开头，则添加前缀
  ///
  /// [str] The string to process / 要处理的字符串
  /// [prefix] The prefix to add / 要添加的前缀
  /// Returns the string with prefix / 返回带前缀的字符串
  ///
  /// Example / 示例: addPrefixIfNot('world', 'hello') => 'helloworld'
  static String addPrefixIfNot(String? str, String prefix) {
    if (isEmpty(str) || isEmpty(prefix)) {
      return str ?? '';
    }

    if (!str!.startsWith(prefix)) {
      return prefix + str;
    }
    return str;
  }

  /// Adds suffix to string if it doesn't already end with it.
  /// 如果字符串不以后缀结尾，则添加后缀
  ///
  /// [str] The string to process / 要处理的字符串
  /// [suffix] The suffix to add / 要添加的后缀
  /// Returns the string with suffix / 返回带后缀的字符串
  ///
  /// Example / 示例: addSuffixIfNot('hello', 'world') => 'helloworld'
  static String addSuffixIfNot(String? str, String suffix) {
    if (isEmpty(str) || isEmpty(suffix)) {
      return str ?? '';
    }

    if (!str!.endsWith(suffix)) {
      return str + suffix;
    }
    return str;
  }

  /// Removes prefix from string if it starts with it.
  /// 如果字符串以前缀开头，则移除前缀
  ///
  /// [str] The string to process / 要处理的字符串
  /// [prefix] The prefix to remove / 要移除的前缀
  /// Returns the string without prefix, or original if no prefix found / 返回不带前缀的字符串，如果未找到前缀则返回原字符串
  ///
  /// Example / 示例: removePrefix('helloworld', 'hello') => 'world'
  static String removePrefix(String? str, String prefix) {
    if (isEmpty(str) || isEmpty(prefix)) {
      return str ?? '';
    }

    if (str!.startsWith(prefix)) {
      return str.substring(prefix.length);
    }
    return str;
  }

  /// Removes prefix from string (case-insensitive).
  /// 移除字符串前缀（忽略大小写）
  ///
  /// [str] The string to process / 要处理的字符串
  /// [prefix] The prefix to remove / 要移除的前缀
  /// Returns the string without prefix, or original if no prefix found / 返回不带前缀的字符串，如果未找到前缀则返回原字符串
  ///
  /// Example / 示例: removePrefixIgnoreCase('HelloWorld', 'hello') => 'World'
  static String removePrefixIgnoreCase(String? str, String prefix) {
    if (isEmpty(str) || isEmpty(prefix)) {
      return str ?? '';
    }

    final strLower = str!.toLowerCase();
    final prefixLower = prefix.toLowerCase();
    if (strLower.startsWith(prefixLower)) {
      return str.substring(prefix.length);
    }
    return str;
  }

  /// Removes suffix from string if it ends with it.
  /// 如果字符串以后缀结尾，则移除后缀
  ///
  /// [str] The string to process / 要处理的字符串
  /// [suffix] The suffix to remove / 要移除的后缀
  /// Returns the string without suffix, or original if no suffix found / 返回不带后缀的字符串，如果未找到后缀则返回原字符串
  ///
  /// Example / 示例: removeSuffix('helloworld', 'world') => 'hello'
  static String removeSuffix(String? str, String suffix) {
    if (isEmpty(str) || isEmpty(suffix)) {
      return str ?? '';
    }

    if (str!.endsWith(suffix)) {
      return str.substring(0, str.length - suffix.length);
    }
    return str;
  }

  /// Removes suffix from string (case-insensitive).
  /// 移除字符串后缀（忽略大小写）
  ///
  /// [str] The string to process / 要处理的字符串
  /// [suffix] The suffix to remove / 要移除的后缀
  /// Returns the string without suffix, or original if no suffix found / 返回不带后缀的字符串，如果未找到后缀则返回原字符串
  ///
  /// Example / 示例: removeSuffixIgnoreCase('HelloWorld', 'WORLD') => 'Hello'
  static String removeSuffixIgnoreCase(String? str, String suffix) {
    if (isEmpty(str) || isEmpty(suffix)) {
      return str ?? '';
    }

    final strLower = str!.toLowerCase();
    final suffixLower = suffix.toLowerCase();
    if (strLower.endsWith(suffixLower)) {
      return str.substring(0, str.length - suffix.length);
    }
    return str;
  }

  /// Formats string by replacing placeholders with arguments.
  /// 通过用参数替换占位符来格式化字符串
  ///
  /// [str] The format string / 格式字符串
  /// [args] Arguments to replace placeholders / 替换占位符的参数
  /// [pattern] Placeholder pattern (default: '%s') / 占位符模式（默认：'%s'）
  ///
  /// Example / 示例:
  /// ```dart
  /// format('Hello %s, you have %s messages', ['Alice', '5'])
  /// // => 'Hello Alice, you have 5 messages'
  /// ```
  static String format(String str, List<Object?> args,
      {Pattern pattern = '%s'}) {
    if (str.isEmpty) return '';
    final result = StringBuffer();
    final strParts = str.split(pattern);
    for (int i = 0; i < strParts.length; i++) {
      result.write(strParts[i]);
      if (i < args.length) {
        result.write(args[i]?.toString() ?? '');
      }
    }
    return result.toString();
  }
}
